package xyz.thoughtset.viewer.modules.ds.core.factory;

import cn.hutool.core.convert.Convert;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import xyz.thoughtset.viewer.common.cache.executor.CacheExecutorHelper;
import xyz.thoughtset.viewer.common.connector.entity.bo.Linker;
import xyz.thoughtset.viewer.common.connector.linker.ConnBuilder;
import xyz.thoughtset.viewer.common.connector.linker.LinkerBuilder;
import xyz.thoughtset.viewer.common.connector.linker.LinkerHelper;
import xyz.thoughtset.viewer.common.exc.entity.ExcInfo;
import xyz.thoughtset.viewer.common.exc.exceptions.ExecException;
import xyz.thoughtset.viewer.executor.core.base.AbstractExecutor;
import xyz.thoughtset.viewer.executor.core.base.DataContext;
import xyz.thoughtset.viewer.executor.core.constants.TypeConstants;
import xyz.thoughtset.viewer.executor.core.entity.QueryBody;
import xyz.thoughtset.viewer.executor.core.entity.QueryParam;
import xyz.thoughtset.viewer.executor.core.factory.ExecutorRegistry;
import xyz.thoughtset.viewer.executor.core.service.QueryBodyService;
import xyz.thoughtset.viewer.modules.ds.core.dao.DsConfigDao;
import xyz.thoughtset.viewer.modules.ds.core.entity.DsConfig;

import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;

@Component
@RequiredArgsConstructor
public class ExecutorManager {
    private final QueryBodyService queryBodyService;
    private final DsConfigDao dsConfigDao;
    private final ConnectFactory connectFactory;
    private final CacheExecutorHelper cacheExecutorHelper;

    public Object execute(String queryId, Map tmpParam){
        QueryBody queryBody = queryBodyService.getById(queryId);

        Map<String, QueryParam> queryMap = queryBody.getParams()
                .stream()
                .collect(Collectors.toMap(QueryParam::getId, Function.identity(), (existing, replacement) -> existing));
//        QueryParam queryParam = queryMap.get(blockParam.getQpId());
//        tmpParamsMap.put(queryParam.getTitle(),
//                Convert.convert(TypeConstants.TYPE_MAP.get(queryParam.getDataType()),value));
        Map paramsMap = new HashMap<>();
        for(Map.Entry<String, QueryParam> entry: queryMap.entrySet()){
            String key = entry.getKey();
            QueryParam queryParam = entry.getValue();
            Object value = tmpParam.get(key);
            if (Objects.isNull(value)) value = queryParam.getDefaultVal();
            paramsMap.put(queryParam.getTitle(),
                    Convert.convert(TypeConstants.TYPE_MAP.get(queryParam.getDataType()),value));
        }
        DsConfig dsConfig = dsConfigDao.selectById(queryBody.getDsId());
        ConnBuilder connBuilder = connectFactory.findConnBuilder(dsConfig);
        AbstractExecutor executor = ExecutorRegistry.findExecutor(connBuilder.getDataLinker().getLinkerType());
        try{
            //todo: cache执行
            return executor.execute(queryBody,paramsMap);
        }catch (ExecException e){
            throw e;
        }catch (Exception e){
            e.printStackTrace();
            ExecException exc = ExcInfo.buildAndThrowExc(e,paramsMap);
            ExcInfo excInfo = exc.getExcInfo();
            excInfo.setFunId(queryId);
            throw exc;
        }

    }

}
